using System;

using Number = System.Single;

namespace DanielSig
{
	public static class XFloat
	{
		public static Number Squared(this Number thisValue)
		{
			return thisValue * thisValue;
		}
		public static Number Sqrt(this Number thisValue)
		{
			return (Number)Math.Sqrt(thisValue);
		}
		public static Number Sign(this Number thisValue)
		{
			return thisValue < 0F ? -1F : 1F;
		}
		public static bool SignBit(this Number thisValue)
		{
			return thisValue < 0F;
		}
		public static Number Clamp(this Number thisValue)
		{
			return thisValue.Clamp(1);
		}
		public static Number Clamp(this Number thisValue, Number limit)
		{
			if(thisValue > limit) return limit;
			if(thisValue < 0F) return 0F;
			return thisValue;
		}
		public static Number ClampBetween(this Number thisValue, Number min, Number max)
		{
			return thisValue.Max(min).Min(max);
		}
		public static Number NormalBetween(this Number thisValue, Number min, Number max)
		{
			return ((thisValue - min) / (max - min)).Clamp();
		}
		public static Number Repeat(this Number thisValue)
		{
			return (thisValue % 1F) + (thisValue < 0F ? 1F : 0F);
		}
		public static Number Repeat(this Number thisValue, Number limit)
		{
			return (thisValue % limit) + (thisValue < 0F ? limit : 0F);
		}
		public static Number RepeatBetween(this Number thisValue, Number min, Number max)
		{
			return min < max ? ((thisValue - min).Repeat(max - min)) + min : min - ((thisValue - max).Repeat(min - max));
		}
		
		public static Number Abs(this Number thisValue)
		{
			return thisValue > 0F ? thisValue : -thisValue;
		}

		public static Number Max(this Number thisValue, Number value)
		{
			return thisValue > value ? thisValue : value;
		}
		public static Number Min(this Number thisValue, Number value)
		{
			return thisValue < value ? thisValue : value;
		}
		/**
		* The same as calling GetNormalizedDistance(center, center, 1F - center)
		*/
		public static Number GetNormalizedDistance(this Number thisValue, Number center)
		{
			if(thisValue > center)
			{
				return (thisValue - center) / (1F - center);
			}
			return (center - thisValue) / center;
		}
		public static Number GetNormalizedDistance(this Number thisValue, Number center, Number negativeUnitSize, Number positiveUnitSize)
		{
			if(thisValue > center)
			{
				return (thisValue - center) / positiveUnitSize;
			}
			return (center - thisValue) / negativeUnitSize;
		}
		public static Number GetDistance(this Number thisValue, Number value)
		{
			if(thisValue > value)
			{
				return thisValue - value;
			}
			return value - thisValue;
		}
		public static bool Aproximates(this Number thisValue, Number value, Number threshold)
		{
			return thisValue.GetDistance(value) <= threshold;
		}
		public static Number MoveTowards(this Number thisValue, Number value, Number maxDistanceDelta)
		{
			if(thisValue - maxDistanceDelta > value)
				return thisValue - maxDistanceDelta;
			if(thisValue + maxDistanceDelta < value)
				return thisValue + maxDistanceDelta;
			return value;
		}
		public static Number Lerp(this Number thisValue, Number value, double amount)
		{
			return (Number)(thisValue + (value - thisValue) * amount);
		}
		public static Number Half(this Number thisValue)
		{
			return thisValue * 0.5F;
		}
		public static Number Double(this Number thisValue)
		{
			return thisValue * 2F;
		}
		public static bool IsBetween(this Number thisValue, Number min, Number max)
		{
			return min < thisValue && thisValue < max;
		}
	}
}

